﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using TntOrm.Structures;
using TntOrm.Attributes;

namespace TntOrm
{
    public class OrmManager
    {
        #region Singleton
        private static OrmManager Instance;

        private OrmManager( )
        { }

        public static OrmManager GetInstance( )
        {
            if( Instance == null )
            {
                Instance = new OrmManager( );
            }

            return Instance;
        }
        #endregion

        private List<TableMapping> Table = new List<TableMapping>( );
        private List<Object> ObjectList = new List<object>( );

        private static Dictionary<string, TableMapping> _TableDict = new Dictionary<string, TableMapping>( );

        public Dictionary<string, TableMapping> TableDict
        {
            get { return _TableDict; }
            set { _TableDict = value; }
        }

        public static TableMapping GetTableByName( string TableName )
        {
            foreach( TableMapping TableIn in _TableDict.Values )
            {
                if( TableIn.TableName == TableName )
                {
                    return TableIn;
                }
            }

            throw new Exception( "Схемы данной таблицы ненайденно. " + TableName );
        }

        public static TableMapping GetTable( string DataName )
        {
            if( _TableDict.ContainsKey( DataName ) )
            {
                return _TableDict[ DataName ];
            }

            throw new Exception( "Схемы данной таблицы ненайденно. " + DataName );
        }

        public static TableMapping GetTable( Type DataType )
        {
            return GetTable( DataType.ToString( ) );
        }

        public void AddObject( Type DataType )
        {
            if( TableDict.ContainsKey( DataType.ToString( ) ) )
            {
                return;
            }

            OrmTable TableAttribute
                = ( ( OrmTable[] ) DataType.GetCustomAttributes( typeof( OrmTable ), true ) )[ 0 ];

            TableMapping DataTypeTable = new TableMapping( TableAttribute.MappingTableName, TableAttribute.Title, TableAttribute.InMenu, DataType );

            PropertyInfo[] DataPropertyInfo
                = DataType.GetProperties( BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty );

            foreach( PropertyInfo PropertyItem in DataPropertyInfo )
            {
                bool IsPrimaryKey = false;
                bool IsLookUp = false;
                OrmReference ReferenceType = null;
                OrmTableField Attribute = null;

                object[] CustomAttributes = PropertyItem.GetCustomAttributes( true );

                foreach( object ObjectAttribute in CustomAttributes )
                {
                    if( ObjectAttribute.GetType( ) == typeof( OrmTableField ) )
                    {
                        Attribute = ( OrmTableField ) ObjectAttribute;
                    }
                    else if( ObjectAttribute.GetType( ) == typeof( OrmLookUp ) )
                    {
                        IsLookUp = true;
                    }
                    else if( ObjectAttribute.GetType( ) == typeof( OrmPrimaryKey ) )
                    {
                        IsPrimaryKey = true;
                    }
                    else if( ObjectAttribute.GetType( ) == typeof( OrmReference ) )
                    {
                        ReferenceType = ( OrmReference ) ObjectAttribute;
                    }
                    else if( ObjectAttribute.GetType( ) == typeof( OrmCrossReference ) )
                    {
                        OrmCrossReference CrossRef = ( OrmCrossReference ) ObjectAttribute;
                        DataTypeTable.CrossReferences.Add( CrossRef.CrossReferenceName, CrossRef );
                    }
                }

                if( Attribute != null )
                {
                    FieldMapping NewField = new FieldMapping( Attribute, PropertyItem.Name, ReferenceType, IsPrimaryKey, IsLookUp );

                    DataTypeTable.AddField( NewField );
                }
            }

            _TableDict.Add( DataType.ToString( ), DataTypeTable );
        }
    }
}